import 'package:bot_toast/bot_toast.dart';
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'base_service.dart';

/// 录像回放管理服务类 - GetX服务
class PlaybackService extends GetxService {
  final BaseService _baseService = BaseService();

  /// 2.5.1 获取录像回放列表
  ///
  /// [serial] 设备ID (必填)
  /// [channel] 通道序号，默认1
  /// [code] 通道编号，与channel二选一
  /// [starttime] 开始时间，格式：YYYY-MM-DDTHH:mm:ss (必填)
  /// [endtime] 结束时间，格式：YYYY-MM-DDTHH:mm:ss
  /// [type] 录像类型：all-所有, time-定时录像, alarm-报警录像, manual-手动录像，默认all
  /// [center] 是否进行中心历史记录检索，默认false
  /// [indistinct] 是否同时进行中心检索和前端检索并将结果统一返回，默认false
  /// [timeout] 超时时间(秒)，默认15
  Future<Map<String, dynamic>> getRecordList({
    required String serial,
    int? channel,
    String? code,
    required String starttime,
    String? endtime,
    String type = 'all',
    bool center = false,
    bool indistinct = false,
    int timeout = 15,
  }) async {
    try {
      final queryParams = <String, dynamic>{
        'serial': serial,
        'starttime': starttime,
        'type': type,
        'center': center,
        'indistinct': indistinct,
        'timeout': timeout,
      };

      if (channel != null) {
        queryParams['channel'] = channel;
      }
      if (code != null && code.isNotEmpty) {
        queryParams['code'] = code;
      }
      if (endtime != null && endtime.isNotEmpty) {
        queryParams['endtime'] = endtime;
      }

      final response = await _baseService.get<Map<String, dynamic>>(
        '/cms/playback/recordlist',
        queryParameters: queryParams,
      );

      if (response.data != null) {
        final data = response.data!;
        if (data['code'] == 0 && data['success'] == true) {
          return data;
        } else {
          throw Exception(data['msg'] ?? '获取录像回放列表失败');
        }
      } else {
        throw Exception('获取录像回放列表响应数据为空');
      }
    } on DioException catch (e) {
      print('获取录像回放列表网络错误: ${e.message}');
      throw Exception('网络环境不佳，请稍后尝试');
    } catch (e) {
      print('获取录像回放列表错误: $e');
      throw Exception('网络环境不佳，请稍后尝试');
    }
  }

  /// 2.5.2 云端录像按月查询
  ///
  /// [serial] 设备ID (必填)
  /// [code] 通道编号 (必填)
  /// [period] 月份，格式：YYYYMM (必填)
  ///
  /// 返回当月有录像的日期列表
  Future<Map<String, dynamic>> queryMonthlyRecords({
    required String serial,
    required String code,
    required String period,
  }) async {
    try {
      final queryParams = {'serial': serial, 'code': code, 'period': period};

      final response = await _baseService.get<Map<String, dynamic>>(
        '/cms/cloudrecord/plan/querymonthly',
        queryParameters: queryParams,
      );

      if (response.data != null) {
        final data = response.data!;
        if (data['code'] == 0 && data['success'] == true) {
          return data;
        } else {
          throw Exception(data['msg'] ?? '云端录像按月查询失败');
        }
      } else {
        throw Exception('云端录像按月查询响应数据为空');
      }
    } on DioException catch (e) {
      print('云端录像按月查询网络错误: ${e.message}');
      throw Exception('网络环境不佳，请稍后尝试');
    } catch (e) {
      print('云端录像按月查询错误: $e');
      throw Exception('网络环境不佳，请稍后尝试');
    }
  }

  /// 2.5.3 云端录像按天查询
  ///
  /// [serial] 设备ID (必填)
  /// [code] 通道编号
  /// [period] 日期，格式：YYYYMMDD (必填)
  ///
  /// 返回当天录像列表
  Future<Map<String, dynamic>> queryDailyRecords({
    required String serial,
    String? code,
    required String period,
  }) async {
    try {
      final queryParams = <String, dynamic>{'serial': serial, 'period': period};

      if (code != null && code.isNotEmpty) {
        queryParams['code'] = code;
      }

      final response = await _baseService.get<Map<String, dynamic>>(
        '/cms/cloudrecord/plan/querydaily',
        queryParameters: queryParams,
      );

      if (response.data != null) {
        final data = response.data!;
        if (data['code'] == 0 && data['success'] == true) {
          return data;
        } else {
          throw Exception(data['msg'] ?? '云端录像按天查询失败');
        }
      } else {
        throw Exception('云端录像按天查询响应数据为空');
      }
    } on DioException catch (e) {
      print('云端录像按天查询网络错误: ${e.message}');
      throw Exception('网络环境不佳，请稍后尝试');
    } catch (e) {
      print('云端录像按天查询错误: $e');
      throw Exception('网络环境不佳，请稍后尝试');
    }
  }

  /// 2.5.4 开始回放录像
  ///
  /// [serial] 设备ID (必填)
  /// [channel] 通道序号，默认1
  /// [code] 通道编号，与channel二选一
  /// [starttime] 开始时间，格式：YYYY-MM-DDTHH:mm:ss (必填)
  /// [endtime] 结束时间，格式：YYYY-MM-DDTHH:mm:ss，默认now
  /// [download] 下载标识，默认false
  /// [downloadSpeed] 下载倍速，仅当download=true时有效，默认4
  /// [smsId] 指定SMS，默认取设备配置
  /// [audio] 是否开启音频，默认config表示读取通道音频开关配置
  /// [transport] 流传输模式，默认config表示读取设备流传输模式配置
  /// [transportMode] 当transport=TCP时有效，指示流传输主被动模式，默认passive
  /// [timeout] 超时时间(秒)，默认15
  ///
  /// 返回回放流信息，包含StreamID和各种播放地址
  Future<Map<String, dynamic>?> startPlayback({
    required String serial,
    int? channel,
    String? code,
    required String starttime,
    String? endtime,
    bool download = false,
    int downloadSpeed = 4,
    String? smsId,
    String audio = 'config',
    String transport = 'config',
    String transportMode = 'passive',
    int timeout = 15,
  }) async {
    try {
      // 验证和格式化时间参数
      final formattedStarttime = _formatDateTimeForAPI(starttime);
      String? formattedEndtime;

      if (endtime != null && endtime.isNotEmpty) {
        formattedEndtime = _formatDateTimeForAPI(endtime);
      }

      // 构建查询参数，确保必填参数存在
      final queryParams = <String, dynamic>{
        'serial': serial,
        'starttime': formattedStarttime,
        'timeout': timeout,
      };

      // 处理endtime参数：如果为空或null，设置为'now'
      if (formattedEndtime != null && formattedEndtime.isNotEmpty) {
        queryParams['endtime'] = formattedEndtime;
      } else {
        queryParams['endtime'] = 'now';
      }

      final response = await _baseService.get<Map<String, dynamic>>(
        '/cms/playback/start',
        queryParameters: queryParams,
      );

      if (response.data != null) {
        final data = response.data!;
        if (data['code'] == 0 && data['success'] == true) {
          return data;
        } else {
          throw Exception(data['msg'] ?? '开始回放录像失败');
        }
      } else {
        throw Exception('开始回放录像响应数据为空');
      }
    } on DioException catch (e) {
      print('开始回放录像网络错误: ${e.message}');
      BotToast.cleanAll();
      BotToast.showText(text: '设备繁忙，请稍后重试');
      return {};
    } catch (e) {
      print('开始回放录像错误: $e');
      BotToast.cleanAll();
      BotToast.showText(text: '设备繁忙，请稍后重试');
      return {};
    }
  }

  /// 2.5.5 停止回放流
  ///
  /// [streamId] 回放流ID (必填)
  ///
  /// 返回下载文件链接（如果有）
  Future<Map<String, dynamic>> stopPlayback({required String streamId}) async {
    try {
      final queryParams = {'streamId': streamId};

      final response = await _baseService.get<Map<String, dynamic>>(
        '/cms/playback/stop',
        queryParameters: queryParams,
      );

      if (response.data != null) {
        final data = response.data!;
        if (data['code'] == 0 && data['success'] == true) {
          return data;
        } else {
          throw Exception(data['msg'] ?? '停止回放流失败');
        }
      } else {
        throw Exception('停止回放流响应数据为空');
      }
    } on DioException catch (e) {
      print('停止回放流网络错误: ${e.message}');
      throw Exception('网络环境不佳，请稍后尝试');
    } catch (e) {
      print('停止回放流错误: $e');
      throw Exception('网络环境不佳，请稍后尝试');
    }
  }

  /// 2.5.6 回放控制
  ///
  /// [streamId] 回放流ID (必填)
  /// [command] 回放控制类型：play, pause, teardown, scale (必填)
  /// [range] command=play时有效，表示从当前位置跳转到指定range(单位s)的时间点播放，默认now
  /// [scale] command=scale时有效，倍数播放倍率，默认2
  ///
  /// 控制回放流的播放状态
  Future<Map<String, dynamic>> controlPlayback({
    required String streamId,
    required String command,
    String range = 'now',
    double scale = 2.0,
  }) async {
    try {
      final queryParams = <String, dynamic>{
        'streamId': streamId,
        'command': command,
      };

      if (command == 'play') {
        queryParams['range'] = range;
      }
      if (command == 'scale') {
        queryParams['scale'] = scale;
      }

      final response = await _baseService.get<Map<String, dynamic>>(
        '/cms/playback/control',
        queryParameters: queryParams,
      );

      if (response.data != null) {
        final data = response.data!;
        if (data['code'] == 0 && data['success'] == true) {
          return data;
        } else {
          throw Exception(data['msg'] ?? '回放控制失败');
        }
      } else {
        throw Exception('回放控制响应数据为空');
      }
    } on DioException catch (e) {
      print('回放控制网络错误: ${e.message}');
      throw Exception('网络环境不佳，请稍后尝试');
    } catch (e) {
      print('回放控制错误: $e');
      throw Exception('网络环境不佳，请稍后尝试');
    }
  }

  /// 2.5.7 录像下载
  ///
  /// [deviceId] 设备ID (必填)
  /// [channelId] 通道ID (必填)
  /// [storeType] 存储类型：1设备存储, 2中心存储 (必填)
  /// [startTime] 开始时间，格式：YYYYMMDDHHmmss (必填)
  /// [endTime] 结束时间，格式：YYYYMMDDHHmmss (必填)
  ///
  /// 返回录像下载地址
  Future<Map<String, dynamic>> downloadRecord({
    required String deviceId,
    required String channelId,
    required int storeType,
    required String startTime,
    required String endTime,
  }) async {
    try {
      final queryParams = {
        'deviceId': deviceId,
        'channelId': channelId,
        'storeType': storeType,
        'startTime': startTime,
        'endTime': endTime,
      };

      final response = await _baseService.get<Map<String, dynamic>>(
        '/cms/playback/download',
        queryParameters: queryParams,
      );

      if (response.data != null) {
        final data = response.data!;
        if (data['code'] == 0 && data['success'] == true) {
          return data;
        } else {
          throw Exception(data['msg'] ?? '录像下载失败');
        }
      } else {
        throw Exception('录像下载响应数据为空');
      }
    } on DioException catch (e) {
      print('录像下载网络错误: ${e.message}');
      throw Exception('网络环境不佳，请稍后尝试');
    } catch (e) {
      print('录像下载错误: $e');
      throw Exception('网络环境不佳，请稍后尝试');
    }
  }

  /// 2.6.3 云端录像按天查询
  ///
  /// [serial] 设备ID (必填)
  /// [code] 通道编号 (可选)
  /// [period] 日期，格式：YYYYMMDD (必填)
  ///
  /// 返回当天云端录像列表
  Future<Map<String, dynamic>> queryCloudDailyRecords({
    required String serial,
    String? code,
    required String period,
  }) async {
    try {
      final queryParams = <String, dynamic>{'serial': serial, 'period': period};

      if (code != null && code.isNotEmpty) {
        queryParams['code'] = code;
      }

      final response = await _baseService.get<Map<String, dynamic>>(
        '/cms/cloudrecord/plan/querydaily',
        queryParameters: queryParams,
      );

      if (response.data != null) {
        final data = response.data!;
        if (data['code'] == 0 && data['success'] == true) {
          return data;
        } else {
          throw Exception(data['msg'] ?? '云端录像按天查询失败');
        }
      } else {
        throw Exception('云端录像按天查询响应数据为空');
      }
    } on DioException catch (e) {
      print('云端录像按天查询网络错误: ${e.message}');
      throw Exception('网络环境不佳，请稍后尝试');
    } catch (e) {
      print('云端录像按天查询错误: $e');
      throw Exception('网络环境不佳，请稍后尝试');
    }
  }

  /// 2.6.4 指定时间段录像播放及下载(mp4合成播放下载)
  ///
  /// [serial] 设备ID (必填)
  /// [code] 通道编号 (必填)
  /// [operate] 调用操作, play-播放, download-下载 (必填)
  /// [starttime] 开始时间, YYYYMMDDHHmmss (必填)
  /// [endtime] 结束时间, YYYYMMDDHHmmss (必填)
  ///
  /// 返回值：
  /// - data.VideoUrl: 录像下载url，无录像返回null
  /// - data.CoverUrl: 录像封面图url，无录像返回null
  Future<Map<String, dynamic>> cloudVideo({
    required String serial,
    required String code,
    required String operate,
    required String starttime,
    required String endtime,
  }) async {
    try {
      final queryParams = <String, dynamic>{
        'serial': serial,
        'code': code,
        'operate': operate,
        'starttime': starttime,
        'endtime': endtime,
      };

      final response = await _baseService.get<Map<String, dynamic>>(
        '/cms/cloudrecord/cloudVideo',
        queryParameters: queryParams,
      );

      if (response.data != null) {
        final data = response.data!;
        // 无论成功失败都返回数据，让调用方自行处理
        return data;
      } else {
        // 返回失败响应，而不是抛出异常
        return {
          'code': 1,
          'success': false,
          'msg': '云端录像下载响应数据为空',
          'data': null,
        };
      }
    } on DioException catch (e) {
      print('云端录像下载网络错误: ${e.message}');
      throw Exception('网络环境不佳，请稍后尝试');
    } catch (e) {
      print('云端录像下载错误: $e');
      throw Exception('网络环境不佳，请稍后尝试');
    }
  }

  /// 暂停回放
  Future<bool> pausePlayback(String streamId) async {
    try {
      await controlPlayback(streamId: streamId, command: 'pause');
      return true;
    } catch (e) {
      print('暂停回放失败: $e');
      return false;
    }
  }

  /// 恢复回放
  Future<bool> resumePlayback(String streamId) async {
    try {
      await controlPlayback(streamId: streamId, command: 'play');
      return true;
    } catch (e) {
      print('恢复回放失败: $e');
      return false;
    }
  }

  /// 设置回放倍速
  Future<bool> setPlaybackSpeed(String streamId, double speed) async {
    try {
      await controlPlayback(streamId: streamId, command: 'scale', scale: speed);
      return true;
    } catch (e) {
      print('设置回放倍速失败: $e');
      return false;
    }
  }

  /// 格式化时间为API需要的格式（YYYY-MM-DDTHH:mm:ss）
  String _formatDateTimeForAPI(String dateTimeStr) {
    try {
      // 尝试解析不同的时间格式
      DateTime dateTime;

      // 如果是DateTime对象字符串，直接解析
      if (dateTimeStr.contains('T') || dateTimeStr.contains('-')) {
        dateTime = DateTime.parse(dateTimeStr);
      } else {
        // 如果是其他格式，尝试转换
        // 这里可以根据实际需要添加更多格式支持
        throw Exception('不支持的时间格式: $dateTimeStr');
      }

      // 格式化为 YYYY-MM-DDTHH:mm:ss
      return '${dateTime.year.toString().padLeft(4, '0')}-'
          '${dateTime.month.toString().padLeft(2, '0')}-'
          '${dateTime.day.toString().padLeft(2, '0')}T'
          '${dateTime.hour.toString().padLeft(2, '0')}:'
          '${dateTime.minute.toString().padLeft(2, '0')}:'
          '${dateTime.second.toString().padLeft(2, '0')}';
    } catch (e) {
      print('时间格式转换失败: $e');
      throw Exception('时间格式错误，请使用 YYYY-MM-DDTHH:mm:ss 格式');
    }
  }
}
